from PySide6 import QtCore
from PySide6.QtGui import QIcon
from PySide6.QtWidgets import QMainWindow, QWidget, QHBoxLayout, QComboBox, QLineEdit, QSizePolicy, QSpacerItem, \
    QToolButton, QTableWidget, QTableWidgetItem, QListWidgetItem

from global_variables import GlobalVariables


class DataListFilter(QMainWindow):
    def __init__(self, app):
        super().__init__()
        self.app = app
        self.ui = app.ui

    @property
    def __data_list_fill_data__(self):
        return self.app.data_list_fill_data

    def add_filter_weight(self, is_insert_field: bool = True):
        self.ui.filter_widgets: QWidget
        if self.ui.filter_widgets.isHidden():
            self.ui.filter_widgets.show()
        filter_widget = QWidget(self.ui.filter_widgets)
        horizontalLayout_6 = QHBoxLayout(filter_widget)
        horizontalLayout_6.setContentsMargins(0, 0, 0, 0)

        # 下拉字段列表
        filter_columns = QComboBox(filter_widget)
        filter_columns.setProperty("has_field", True)
        horizontalLayout_6.addWidget(filter_columns)
        if len(GlobalVariables.DATA_LIST_HEADER_MAP) != 0 and is_insert_field:
            filter_columns.addItems(GlobalVariables.DATA_LIST_HEADER_MAP)

        # 下拉操作符
        filter_operator = QComboBox(filter_widget)
        filter_operator.addItem("=")
        filter_operator.addItem("!=")
        filter_operator.addItem(">")
        filter_operator.addItem(">=")
        filter_operator.addItem("<")
        filter_operator.addItem("<=")
        filter_operator.addItem("like")

        horizontalLayout_6.addWidget(filter_operator)

        filter_value = QLineEdit(filter_widget)
        sizePolicy1 = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
        sizePolicy1.setHorizontalStretch(0)
        sizePolicy1.setVerticalStretch(0)
        sizePolicy1.setHeightForWidth(filter_value.sizePolicy().hasHeightForWidth())
        filter_value.setSizePolicy(sizePolicy1)
        filter_value.setClearButtonEnabled(True)

        horizontalLayout_6.addWidget(filter_value)

        horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)

        horizontalLayout_6.addItem(horizontalSpacer)

        filter_del_button = QToolButton(filter_widget)
        filter_del_button.setText('-')

        horizontalLayout_6.addWidget(filter_del_button)

        filter_add_button = QToolButton(filter_widget)
        filter_add_button.setText('+')

        horizontalLayout_6.addWidget(filter_add_button)

        self.ui.verticalLayout_9.addWidget(filter_widget)

        filter_value.returnPressed.connect(self.filter_value_return_pressed)
        filter_del_button.clicked.connect(self.filter_del_button_clicked)
        filter_add_button.clicked.connect(self.filter_add_button_clicked)

    def filter_del_button_clicked(self):
        parent = self.sender().parent()
        if parent.parent().objectName() == 'filter_widgets':
            children = parent.parent().findChildren(QWidget, options=QtCore.Qt.FindChildOption.FindDirectChildrenOnly)
            if len(children) == 1:
                return
            parent.deleteLater()

    def filter_add_button_clicked(self):
        self.add_filter_weight()

    def set_filter_columns(self):
        for child_widget in self.ui.filter_widgets.findChildren(QWidget):
            for child in child_widget.findChildren(QComboBox):
                child: QComboBox
                if child.property('has_field') is True and child.count() == 0:
                    child.addItems(GlobalVariables.DATA_LIST_HEADER_MAP)

    def reset_filter(self):
        # 清空多余的筛选
        for c in self.ui.filter_widgets.findChildren(QWidget, options=QtCore.Qt.FindChildOption.FindDirectChildrenOnly):
            c.deleteLater()
        # 添加新的筛选
        self.add_filter_weight(False)

    def filter_value_return_pressed(self):
        self.__data_list_fill_data__.header_clicked_order_by(self.ui.data_list, -1)

    def filter_value(self, obj: QTableWidget = None):
        children_widget = self.ui.filter_widgets.findChildren(QWidget,
                                                              options=QtCore.Qt.FindChildOption.FindDirectChildrenOnly)
        if len(children_widget) == 0:
            return

        table_name = self.get_table_name()
        if table_name is None:
            return
        order_by = {}
        if isinstance(obj, QTableWidget):
            for column_index, field in enumerate(GlobalVariables.DATA_LIST_HEADER_MAP):
                item: QTableWidgetItem = obj.horizontalHeaderItem(column_index)
                if hasattr(item, 'desc') and item.desc in ['DESC', 'ASC']:
                    order_by[field] = item.desc

        where = self.filter_widget_to_where(children_widget)
        GlobalVariables.DATA_LIST_PAGE_NUM = 1
        page_num = GlobalVariables.DATA_LIST_PAGE_NUM
        limit = int(self.ui.data_page_limit.currentText())
        self.__data_list_fill_data__.data_list_fill_data(table_name=table_name,
                                                         where=where,
                                                         limit=limit,
                                                         page_num=page_num,
                                                         order_by=order_by)

    def filter_widget_to_where(self, children_widget: list):
        where = []
        for child_widget in children_widget:
            line_edit = child_widget.findChild(QLineEdit)
            value = line_edit.text()
            if len(children_widget) == 1 and len(value) == 0:
                return where

            field = ''
            op = ''
            for child in child_widget.findChildren(QComboBox):
                if child.property('has_field') is True:
                    field = child.currentText()
                else:
                    op = child.currentText()
            if len(field) == 0 or len(op) == 0:
                continue
            where.append([field, op, value])
        return where

    def get_table_name(self):
        item = self.ui.table_list.currentItem()
        if isinstance(item, QListWidgetItem):
            return item.text()
        return None
